# TODO 列表的高级操作

# 1、列表推推导或者叫做列表解析
# 列表推导式（List Comprehension）是一种高效创建列表的方式，但如果推导式过于复杂，可能会降低代码的可读性。一般建议只在简单的情况下使用列表推导式。
# 列表推导式在内存中会创建一个新的列表，如果原列表很大，可能会占用大量内存。在这种情况下，可以考虑使用生成器表达式或者其他懒加载技术。

# 列表推导式：这是一种高效创建和转换列表的方式。比如，我们可以创建一个包含 1 到 10 的平方的列表：
squares = [i ** 2 for i in range(1, 11, 1)]  # 快速生成 1 - 10 的平方
print(squares)  # 输出：[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

# 带有条件的列表推导式：我们可以在列表推导式中使用 if 条件来过滤元素。比如，我们可以创建一个包含 1 到 10 中所有奇数的平方的列表：
# eg: 获取 1-10内的基数
val = [i for i in range(1, 11, 1) if i % 2 != 0]
print(val)  # [1, 3, 5, 7, 9]

#  嵌套列表解析
# 嵌套列表解析允许在一个列表解析中使用多个循环，以创建更复杂的列表结构
# 创建一个包含矩阵的列表
matrix = [[x for x in range(1, 4)] for _ in range(1, 4)]
print(matrix)  # 输出: [[1, 2, 3], [1, 2, 3], [1, 2, 3]]
# 上面代码的解释:
# 这段代码创建了一个3x3的矩阵，使用的是列表推导式。具体来说，它生成了一个包含3个列表的列表，这3个列表都包含了1到3的整数。
# 让我们详细解释下这段代码：
# 外部的 for _ in range(1, 4) 生成了3次循环，每次循环都会生成一个列表。这里的 _ 是一个常用的习惯用法，用于表示我们并不关心循环变量的值。
# 对于每次循环，内部的列表推导式 [x for x in range(1, 4)] 生成了一个包含3个整数（1, 2, 3）的列表。
# 所以，最终生成的是这样一个列表：[[1, 2, 3], [1, 2, 3], [1, 2, 3]]，你可以将其视为一个3x3的矩阵。


# 2、排序：列表有一个 sort 方法可以进行就地排序，也就是说，原列表将被排序后的列表覆盖。另外，Python 还有一个内置的 sorted 函数可以用来排序，它会返回一个新的排序后的列表，而不改变原列表。
numbers = [6, 1, 5, 2, 3, 4]
numbers.sort()  # 修改当前列表中的元素顺序
print(numbers)  # 输出：[1, 2, 3, 4, 5, 6]

numbers = [6, 1, 5, 2, 3, 4]
sorted_numbers = sorted(numbers)  # 为当前列表进行排序,并生成一个新的列表
print(numbers)  # 输出：[6, 1, 5, 2, 3, 4]，原列表未改变
print(sorted_numbers)  # 输出：[1, 2, 3, 4, 5, 6]

# 3、列表切片
# 在使用 Python 列表的切片操作时，需要注意以下几点：
# 切片操作不会修改原列表，而是生成一个新的子列表。这意味着，如果你的原列表非常大，切片操作可能会消耗大量的内存。
# 切片的起始索引是包含的，结束索引是不包含的。例如，my_list[1:3] 包含了 my_list 中索引为 1 和 2 的元素，但不包含索引为 3 的元素。
# 切片的索引可以为负，表示从列表的末尾开始计数。例如，my_list[-1] 返回列表的最后一个元素。
# 当起始索引或结束索引超出列表的范围时，Python 不会报错，而是返回一个尽可能大的子列表。

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
sublist = numbers[2:7]  # 获取索引2到索引6的元素（不包含索引7）
print(sublist)  # 输出: [3, 4, 5, 6, 7]
even_numbers = numbers[1:10:2]  # 获取从索引1到索引9的元素，步长为2
print(even_numbers)  # 输出: [2, 4, 6, 8, 10]

# 创建子列表：你可以使用切片操作来创建一个列表的子列表。在这个例子中，my_list[1:4] 创建了一个包含 my_list 中索引为 1 到 3 的元素的新列表。 例如：
my_list = [0, 1, 2, 3, 4, 5]
print(my_list[1:4])  # 输出：[1, 2, 3]

# 省略起始或结束索引：当你省略起始索引时，Python 将从列表的开始处进行切片；当你省略结束索引时，Python 将一直切片到列表的末尾。例如：
my_list = [0, 1, 2, 3, 4, 5]
print(my_list[:3])  # 输出：[0, 1, 2]
print(my_list[3:])  # 输出：[3, 4, 5]

# 使用步长：切片操作还可以指定一个步长（step），表示每隔多少个元素取一个。在这个例子中，my_list[::2] 创建了一个包含 my_list 中所有偶数索引元素的新列表。例如：
my_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(my_list[::2])  # 输出：[0, 2, 4, 6, 8]

# 反转列表：你可以使用步长为 -1 的切片操作来反转一个列表。例如：
my_list = [0, 1, 2, 3, 4, 5]
print(my_list[::-1])  # 输出：[5, 4, 3, 2, 1, 0]


